#pragma once
#include"Thread.hpp"
#include"Mutex.hpp"
#include<vector>
#include<queue>
#include<mutex>
#include<pthread.h>
#include<unistd.h>

using namespace myThread;

const int gnum = 3;

template<class T>
class ThreadPool;

template<class T>
class ThreadData
{
public:
    ThreadPool<T>* threadPool;
    std::string threadname;
    ThreadData(ThreadPool<T> *tp,const std::string& n):threadPool(tp),threadname(n) {}
};

template<class T>
class ThreadPool
{
private:
    //单例模式
    ThreadPool(const int& num = gnum):_num(num)
    {
        pthread_mutex_init(&_mutex,nullptr);
        pthread_cond_init(&_cond,nullptr);
        for(int i=0;i<num;i++) _threads.push_back(new Thread());
    }

    //禁掉赋值和拷贝构造
    void operator=(const ThreadPool& )=delete;
    ThreadPool(const ThreadPool& )=delete;

    static void* handerTask(void* args)
    {
        ThreadData<T> *td = (ThreadData<T> *)args;
        while(true)
        {
            T t;
            {
                LockGuard lockguard(td->threadPool->mutex());
                while(td->threadPool->IsQueueEmpty())
                    td->threadPool->threadWait();
                t = td->threadPool->pop();
            }
            std::cout<<td->threadname<<" 获取了一个任务: "<<t.toTaskstring()<<" 处理完成 ,结果是: "<<t()<<std::endl;
        }

        delete td;
        return nullptr;
    }

public:
    void lockQueue() {pthread_mutex_lock(&_mutex);}
    void unlockQueue() {pthread_mutex_unlock(&_mutex);}
    bool IsQueueEmpty() {return _task_queue.empty();}
    bool threadWait() {pthread_cond_wait(&_cond,&_mutex);}
    pthread_mutex_t *mutex() {return &_mutex;}

    T pop()
    {
        T t = _task_queue.front();
        _task_queue.pop();
        return t;
    }

public:
    void run()
    {
        for(const auto& item : _threads)
        {
            ThreadData<T>* td = new ThreadData<T>(this,item->threadname());
            item->start(handerTask,td);//handerTask作为回调
            std::cout<<item->threadname()<<"start..."<<std::endl;
        }
    }

    void push(const T& in)
    {
        LockGuard lguard(&_mutex);
        _task_queue.push(in);
        pthread_cond_signal(&_cond);
    }

    //单列模式
    static ThreadPool<T>* getInstance()
    {
        if(nullptr == tp)//判断成功再上锁可以提高效率
        {
            _singlock.lock();
            if(nullptr == tp) tp = new ThreadPool<T>();
            _singlock.unlock();
        }
        return tp;
    }

    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
        // _threads.push_back(new Thread());
        for(auto& item : _threads) delete item;
    }

private:
    int _num;
    std::vector<Thread*> _threads;
    std::queue<T> _task_queue;
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;

    static ThreadPool<T>*tp;
    static std::mutex _singlock;
};

template<class T>
ThreadPool<T>* ThreadPool<T>::tp = nullptr;

template<class T>
std::mutex ThreadPool<T>::_singlock;